import { Message } from "element-ui";
import { globalApi } from "@/request";
import { ROOT_TENANT_SPACE_NAME } from "@/const";  

export const getCapacityUnit = (unit) => {
    let unitTxt = ''
    switch(unit){  // 1.MB; 2.GB; 3.TB
        case 1: unitTxt = 'MB'; break; 
        case 2: unitTxt = "GB"; break;
        case 3: unitTxt = 'TB'; break;
        default: break;
    }
    return unitTxt
}

const UNIT_PARSE_LIST = [
    { from: 'MB', to: 'GB', parse: value => parseFloat(value / 1024).toFixed(2) },
    { from: 'MB', to: 'TB', parse: value => parseFloat(value / 1024 / 1024).toFixed(2) },
    { from: 'GB', to: 'MB', parse: value => parseFloat(value * 1024).toFixed(2) },
    { from: 'GB', to: 'TB', parse: value => parseFloat(value / 1024).toFixed(2) },
    { from: 'TB', to: 'MB', parse: value => parseFloat(value * 1024 * 1024).toFixed(2) },
    { from: 'TB', to: 'GB', parse: value => parseFloat(value * 1024).toFixed(2) },
]
/**
 * @description 计算机存储单位换算
 * @param {Number} value 要换算的值
 * @param {String} unitFrom 原单位
 * @param {String} unitTo 目标单位
 */
export const parseValueByUnit = (value, unitFrom, unitTo) => {
    value = parseFloat(value)
    if (unitFrom === unitTo) return value
    let valueConversion = UNIT_PARSE_LIST.filter(item => {
        return item.from === unitFrom && item.to === unitTo
    })[0].parse
    return parseFloat(valueConversion(value))
}

// 数据格式化
export const formatNumber = function(value) {
    
}

// iframe下载文件
export const downLoadFile = (url) => {
    const elIframe = document.createElement('iframe');
    elIframe.src = url;
    elIframe.style.display = 'none';
    elIframe.onload = function() {
        // 下载后，移除当前iframe
        let iframeTxt = elIframe.contentDocument.documentElement.innerText || JSON.stringify({})
        const resObj = JSON.parse(iframeTxt);
        if ( resObj.code == '-1' ) {
            Message.error('下载失败，请稍后重试！');
        }
        document.body.removeChild(elIframe);
    }
    document.body.appendChild(elIframe);
}
export const downloadKeytab = function(userId) {
    const url = `/dataspace/api/v1/user/downloadKeytab?userId=${userId}`;
    downLoadFile(url);
}

/**
 * @author fujiafeng
 * @description 密码正则校验（1.8-20位 2.不能纯数字/纯字母/纯特殊字符 3.由数字、字母、下划线及限定字符组成）
 * @param value(String) 密码字符串
 * @return Boolean 合法时返回true
*/
export const validatePassword = function(value) {
    const reg = /(?!^(\d+|[a-zA-Z]+|[_~!@#$%^&*?]+)$)^[\w~!@#$%^&*?]{8,20}$/;
    return reg.test(value);
}
/**
 * @author fujiafeng
 * @description 密码分步骤校验提示（steps: 1.必填项 2.位数 3.格式）
 * @param pwd(String) 密码
 * @param required(Boolean) 必填项校验（默认 false）
 * @return String 校验提示信息Msg（数据合法时，返回空字符串''）
*/
export const validatePasswordByStep = function(pwd='', required=false) {
    let Msg = '';
    if (required && pwd === '') {
        Msg = '请输入密码';
    } else if (!/^.{8,20}$/.test(pwd)) {
        Msg = '密码长度为 8-20 位'; 
    } else if (!validatePassword(pwd)) {
        Msg = '请输入数字、字母及特殊字符（_~!@#$%^&*?）的组合'
    }
    return Msg;
}
/**
 * @description Element-UI的表单校验 密码、确认密码校验
 */
export const validatePwdForElementUI = (rule, value, callback) => {
    // element-ui 表单校验必须调用 callback() 回调
    const msg = validatePasswordByStep(value, true);
    __validateCbForElementUI(msg, callback);
}
export const validateVerifyPwdForElementUI = (value, firstPwd, callback) => {
    if (value === '') {
        callback(new Error('请再次输入密码'));
    } else if (value !== firstPwd) {
        callback(new Error('两次输入密码不一致!'));
    } else {
        callback();
    }
}

/**
 * @description Element-UI的表单校验 用户名/租户名 (steps：1.必填项 2.位数1-8位 3.字母或数字、字母的组合)
 * @param config{Object} 属性auth-租户/用户，status-去重判别条件
 */
export const validateUserNameForElementUI = (value, config={auth: '用户', status: ''}, callback, setCheckingUserNameCallback) => {
    const reg = /(?!^(\d+)$)^[A-Za-z0-9]{1,12}$/;
    if (value === '') {
        callback(new Error(`请输入${config.auth}名称`));
    // } else if (value && !/^.{1,8}$/.test(value)) {
        // callback(new Error('名称长度为 1-8 位'));
    } else if (value && !/^.{1,12}$/.test(value)) { // 山东GAT 项目，修改名称长度为 12
        callback(new Error('名称长度为 1-12 位'));
    } else if (value && !reg.test(value)) {
        callback(new Error(`请输入字母或字母、数字组合的${config.auth}名`))
    } else { // 去重校验
        if (config.status === 'CREATE') {
            if (typeof setCheckingUserNameCallback === 'function'){
                setCheckingUserNameCallback(true);
            }
            globalApi.nameExist({userName: value}).then(res => {
                callback();
                if (typeof setCheckingUserNameCallback === 'function'){
                    setCheckingUserNameCallback(false);
                }
            }).catch(err => {
                callback(new Error(`该${config.auth}已存在！`));
                if (typeof setCheckingUserNameCallback === 'function'){
                    setCheckingUserNameCallback(false);
                }
            })
        } else {
            callback();
        }
    }
}

/**
 * @description 用户名/租户名查询 格式校验(数字或字母)
 * @param value{String} 查询字段
 * @return Boolean
 */
export const validateSearchName = (value='') => {
    if (value && !/^[A-Za-z0-9]+$/.test(value)) {
        Message.error('查询内容请输入字母或数字');
        return false;
    }
    return true;
}

/**
 * @description 数据格式校验（正整数）
 * @param value{Number} 校验字段
 * @param config{Object} 校验必填项（required,requireMsg-必填项，max-最大值）
 * @return String 返回校验信息
 */
export const validatePositiveInteger = (value, config={required: false, requireMsg: '请输入正整数', max: undefined}) => {
    const reg = /^[1-9]\d*$/;
    if (config.required && value === '') {
        return config.requireMsg;
    } else if (!reg.test(value)) {
        return '请输入正整数';
    } else if (config.max === 0 || (config.max && config.max < value)) { // max可能为0
        return `请输入小于等于 ${config.max} 的正整数`;
    } else {
        return '';
    }
}
/**
 * @description Element-UI的表单校验 HDFS文件配额
 */
export const validateHdfsFileNumForElementUI = (rule, value, callback) => {
    let msg = validatePositiveInteger(value, {required: true, requireMsg: '请输入HDFS文件配额'});
    __validateCbForElementUI(msg, callback);
}
/**
 * @description Element-UI的表单校验 回调函数callback()
 */
export const __validateCbForElementUI = (msg, callback) => {
    if (msg) {
        callback(new Error(msg));
    } else {
        callback();
    }
}

// 重置表单
export const resetForm = (form) => {
    form.resetFields();
    form.clearValidate();
}


/**
 * @author fujiafeng
 * @description 格式化租户资源表单
 * @param targetObj{Object} 资源表单
 * @param name{String} 资源名称
 * @param sObj{Object} 资源对象(hdfs/hive/hbase/yarn/kafka)
 * @param defaultName{String} 默认的资源空间名称（租户名）
 */
export const formatServiceObj = (targetObj, name, sObj={}, defaultName) => {
    sObj = sObj || {};
    switch(name) {
        case 'hdfs':
            targetObj.hdfs.id = sObj.id || '';
            targetObj.hdfs.url = sObj.url || `dataspace/${defaultName}`;
            targetObj.hdfs.capacity = sObj.capacity || 0;
            targetObj.hdfs.unit = sObj.unit.toString();
            targetObj.hdfs.fileNum = sObj.fileNum || 0;
            break;
        case 'hive':
            targetObj.hive.id = sObj.id || '';
            targetObj.hive.databaseName = sObj.databaseName || defaultName;
            break;
        case 'hbase':
            targetObj.hbase.id = sObj.id || '';
            targetObj.hbase.spaceName = sObj.spaceName || defaultName;
            break;
        case 'yarn':
            targetObj.yarn.id = sObj.id || '';
            targetObj.yarn.queueName = sObj.queueName || defaultName;
            targetObj.yarn.ratio = sObj.ratio || 0;
            break;
        case 'kafka':
            targetObj.kafka.id = sObj.id || '';
            targetObj.kafka.kafkaTopicNum = sObj.kafkaTopicNum || 0;
            // targetObj.kafka.topicName = sObj.topicName || '';
            // targetObj.kafka.partitionNum = sObj.partitionNum || 0;
            // targetObj.kafka.replication = sObj.replication || 0;
            break;
        default:
            return targetObj;
    }
    return targetObj;
}
/**
 * @author fujiafeng
 * @description 清除serviceForm
 * @param hasCheckbox{Boolean} 是否包含checkedServices属性（TenantDrawer中）
 * @param showKafa{Boolean} 是否展示 Kafka信息（租户详情中）
 */
export const cleanServiceForm = (hasCheckbox = false, showKafa = false) => {
    let obj = {
        hdfs: { id: '', url: '', capacity: 0, unit: '2', fileNum: 0 },
        hive: { id: '', databaseName: '' },
        hbase: { id: '', spaceName: '' },
        yarn: { id: '', queueName: '', ratio: 0 }
    };
    if (showKafa) {
        // obj.kafka = { id: '', topicName: '', partitionNum: 0, replication: 0 };
        obj.kafka = { id: '', kafkaTopicNum: 0 };
    }
    if (hasCheckbox) {
        obj.checkedServices = ['hdfs', 'hive', 'hbase', 'yarn']; // 开启的服务
    }
    return obj;
}


export function escapeHTML(text) {
    return String(text)
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&apos;')
}

// export const sleep = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms))
export const sleep = function(ms = 0) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve()
        }, ms);
    })
}

// 未登录或登录失效后，把localstorage里面的数据清了
export const clearLocalStorage = () => {
    window.localStorage.removeItem('lastLoginerName')
    window.localStorage.removeItem('lastRole')
    window.localStorage.removeItem('modifyPass')
    window.localStorage.removeItem('lastInstalledServices')
}

/**
 * @author wangzhixiang
 * @description 用于两个对象的深比较(目标对象与源对象的比较))，可通过config中的compareKeys配置，来限定比较的字段
 * @param obj{Object} 源对象
 * @param target{Object} 目标对象
 * @return Boolean
*/
export const isDeepEqual = (obj, target, config) => {
    
}
/**
 * @author cuishoujia   2019-11-11
 * @description 获取对象的类型  此处不用typeof
 * @param {Object 必传} obj 需要获取类型的对象 
 */
function getObjectType(obj) {
    //以下函数返回obj的类型，如"[object Array]",从第7位至倒数第二位即为对象类型
    let typeStr = Object.prototype.toString.call(obj);
    return typeStr.substring(8, typeStr.length - 1);
}
/**
 * @author cuishoujia   2019-11-11
 * @description 循环遍历比较对象或者数组的各个元素
 * @param {Object 必传} source 需要遍历比较的第一个对象
 * @param {Object 必传} target 需要遍历比较的第二个对象
 * @param {Object 必传} isIgnoreSort 当比较到数组时是否忽略排序
 * @param {Array 选传} compareKeys 通过指定某些字段，判断两个对象是否相同
 */
function loopCompare(source, target, isIgnoreSort, compareKeys) {
    let temp = compareKeys || source;
    let config = {
        isIgnoreSort: isIgnoreSort
    };
    for (let property in temp) {
        //此处用for--in循环，适用于数组/对象
        //判断source中的每个属性，在target中是否都存在，且其方式（自有/继承）相同
        property = compareKeys ? compareKeys[property] : property;
        if (source.hasOwnProperty(property) !== target.hasOwnProperty(property)) return false;
        if (!deepCompare(source[property], target[property], config)) return false;
    }
    return true;
}

/**
 * @author cuishoujia   2019-11-11
 * @description 比较两个对象是否相等   如果指定字段，前两个参数必须为Object
 * @param {Object 必传} source 比较的第一个对象 
 * @param {Object 必传} target 比较的第二个对象
 * @param {Object 可选} config 
 *      {compareKeys:[指定需要比较的字段],isIgnoreSort:是否忽略数组排序true/false}
 */
export const deepCompare = function(source, target, config = {}) {
    const { compareKeys = [], isIgnoreSort = true } = config

    //先排除undefined\null 两个特殊属性，防止下面调用hasOwnProperty报错
    //两个参数如果有一个不存在，此时两个参数相等则返回true,不相等则返回false
    if (!source || !target) {
        //NaN不等于自身 所以当两个值同时为NaN,这里就视为相等
        if (source !== source && target !== target) return true;
        return source === target;
    }

    //获取两个对象的类型
    let typeSource = getObjectType(source);
    let typeTarget = getObjectType(target);

    //如果有指定的比较字段，需要先确保前两个参数为Object,否则返回false
    if (compareKeys.length > 0) {
        if(typeSource !== "Object" || typeTarget !== "Object"){
            return false;
        }
        return loopCompare(source, target, isIgnoreSort, compareKeys);
    }

    //两个参数类型不同，返回false
    if (typeSource !== typeTarget) return false;

    //数字、字符串、布尔等基本数据类型，直接比较
    if (typeSource === "Number" || typeSource === "Boolean" || typeSource === "String") {
        return source === target;
    }

    //日期、正则、symbol类型，转为字符串比较
    if (typeSource === "Date" || typeSource === "Regex" || typeSource === "Symbol") {
        return source.toString() === target.toString();
    }

    //set map 转为数组比较
    if (typeSource === "Set" || typeSource === "Map") {
        return deepCompare([...source], [...target]);
    }

    //如两个参数为对象，先比较其key个数是否相等,再遍历其元素
    if (typeSource === "Object") {
        return (Object.keys(source).length === Object.keys(target).length) && loopCompare(source, target, isIgnoreSort);
    }

    //如两个参数为数组，先比较其长度是否相等
    if (typeSource === "Array") {
        if (source.length !== target.length) return false;

        //判断是否忽略排序
        if (!isIgnoreSort) return loopCompare(source, target, isIgnoreSort);

        //定义变量接受目标数组，因为后面有删除元素操作，需要保护源数据
        let tempObject = [...target];
        for (let property in source) {
            let tempObjectPosition = tempObject.findIndex(function(value) {
                return deepCompare(value, source[property]);
            })
            if (tempObjectPosition < 0) return false;
            //此处必须删掉目标里的对应元素，防止类似[1,2,2]和[1,2,3]的比较
            tempObject.splice(tempObjectPosition, 1);
        }
        return true;
    }
    //参数类型均不属于上述所有类型，即表示不支持，返回false
    return false;
};

let NUM = 0

/**
 * @author wangzhixiang
 * @description 获取uuid
 * @return String
*/
export const getUUid = () => {
    return Math.random().toString(36).substr(2) + NUM++;
}